#include "qtvisioserver.h"
#include "ui_qtvisioserver.h"

QtVisioServer::QtVisioServer(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::QtVisioServer)
{
    _server = new QTcpServer(this);
    _serverStatus=false;
    _port=50000;
    _model=new QStringListModel();
    _dataSize=0;

    ui->setupUi(this);
    connect(ui->buttonServer, SIGNAL(clicked()), this, SLOT(serveurConnecDisconnect()));
    connect(_server, SIGNAL(newConnection()), this, SLOT(clientConnect()));
}

QtVisioServer::~QtVisioServer()
{
    delete ui;
    delete _server;
    delete _model;
}

void QtVisioServer::serveurConnecDisconnect(){
    if (_serverStatus==false){

        if (!_server->listen(QHostAddress::Any, _port))
        {
            _serverStatus=false;
            ui->serverState->setText("Erreur démarrage serveur<br />(" + _server->errorString()+")");
        }
        else
        {
            _serverStatus=true;
            ui->serverState->setText("Serveur démarré sur le port " + QString::number(_server->serverPort()));
            ui->buttonServer->setText("Stopper le serveur");

        }
    }
    else {
        _server->close();
        ui->serverState->setText("Serveur déconnecté");
        ui->buttonServer->setText("Lancer le serveur");
        _serverStatus=false;
        _clients.clear();

        updateClientsList();
    }
}

void QtVisioServer::clientConnect(){

    QTcpSocket * newClient= _server->nextPendingConnection();
    QString clientName="test";

    QPair <QTcpSocket *,QString>pair(newClient,clientName);
    _clients<<pair;
    connect(newClient, SIGNAL(disconnected()), this, SLOT(clientDisconnect()));
    connect(newClient, SIGNAL(readyRead()), this, SLOT(newData()));

    updateClientsList();
}

void QtVisioServer::clientDisconnect(){

    QTcpSocket * oldClient = qobject_cast<QTcpSocket *>(sender());
    if (oldClient == 0)
        return;

    int size=_clients.size();
    for(int i=0;i<size;i++){
        if (_clients[i].first==oldClient)
        //_clients.removeOne(oldClient);
            _clients.removeAt(i);
    }
    oldClient->deleteLater();

    updateClientsList();
}

void QtVisioServer::newData(){

    QTcpSocket *client = qobject_cast<QTcpSocket *>(sender());
    if (client == 0)
        return;

    QDataStream in(client);

    if (_dataSize == 0)
    {
        if (client->bytesAvailable() < (int)sizeof(quint16)) // On n'a pas reçu la taille du message en entier
            return;

        in >> _dataSize; // Si on a reçu la taille du message en entier, on la récupère
    }

    // Si on connaît la taille du message, on vérifie si on a reçu le message en entier
    if (client->bytesAvailable() < _dataSize) // Si on n'a pas encore tout reçu, on arrête la méthode
        return;


    // Si ces lignes s'exécutent, c'est qu'on a reçu tout le message : on peut le récupérer !
    QString message;
    in >> message;


    // 2 : on renvoie le message à tous les clients
    sendToAll(message);

    // 3 : remise de la taille du message à 0 pour permettre la réception des futurs messages
    _dataSize = 0;

}

void QtVisioServer::sendToAll(const QString &message){

    QByteArray packet;
    QDataStream out(&packet, QIODevice::WriteOnly);

    out << (quint16) 0; // On écrit 0 au début du paquet pour réserver la place pour écrire la taille
    out << message; // On ajoute le message à la suite
    out.device()->seek(0); // On se replace au début du paquet
    out << (quint16) (packet.size() - sizeof(quint16)); // On écrase le 0 qu'on avait réservé par la longueur du message


    // Envoi du paquet préparé à tous les clients connectés au serveur
    for (int i = 0; i < _clients.size(); i++)
        _clients[i].first->write(packet);

}

void QtVisioServer::updateClientsList(){

    QStringList clientsList;
    int cSize=_clients.count();

    for(int i=0;i<cSize;i++)
       clientsList<<_clients[i].second +" ("+_clients[i].first->localAddress().toString()+")";

    _model->setStringList(clientsList);
    ui->clientsListView->setModel(_model);

}

void sendClientsList(){

}
